package zeroj.helper;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 
 * 
 * @author lyl(lylsir at gmail dot com)
 * 
 * @since 1.0
 * 
 * 2008-9-9
 */
public final class ClassLoaderUtil {

	private static final Log log = LogFactory.getLog(ClassLoaderUtil.class);
	
	public static List<Class<?>> loadPackageClasses(Package pack) {
		
		return loadPackageClasses(pack.getName());
	}
	public static List<Class<?>> loadPackageClasses(String packageName) {
		
		return loadPackageClasses(packageName, false);
	}
	public static List<Class<?>> loadPackageClasses(String packageName, boolean subPackage) {
		
		String dirName = packageName.replace('.', '/');
		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
		List<Class<?>> classes = new ArrayList<Class<?>>();
		Enumeration<URL> urls = null;
		try {
			urls = classLoader.getResources(dirName);
		} catch (IOException e) {
			e.printStackTrace();
		}
		if(urls == null || ! urls.hasMoreElements()) {
			
			try {
				urls = ClassLoaderUtil.class.getClassLoader().getResources(dirName);
			} catch (IOException e) {
				log.warn("load dir " + dirName, e);
			}
		}
		if(urls == null)
			return classes;
		while(urls.hasMoreElements()) {
			URL url = urls.nextElement();
			URI uri;
			try {
				uri = url.toURI();
			} catch (URISyntaxException e) {
				continue;
			}
			File dir = new File(uri);
			if(dir.exists() && dir.isDirectory()) {
				String[] files = dir.list();
				for(String fileName : files) {
					
					if(fileName.endsWith(".class")) {
						
						String className = packageName + "." + fileName;
						className = className.substring(0, className.length() - ".class".length());
						Class<?> clz = loadClass(className);
						if(clz != null) 
							classes.add(clz);
					} else if(subPackage){
						classes.addAll(loadPackageClasses(packageName + "." + fileName, true));
					}
				}
			}
		}
		return classes;
	}
	
    public static Class<?> loadClass(String className) {
    	
    	if(log.isDebugEnabled())
    		log.debug("load class " + className);
    	try {
			return Thread.currentThread().getContextClassLoader().loadClass(className);
		} catch (ClassNotFoundException e) {
			log.warn("load class not found " + className);
			return null;
		}
    }
    public static Properties loadClassProperties(Class<?> clz) {
    	
    	String fileName = clz.getName().replace('.', '/') + ".properties";
    	InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
    	if(is == null)
    		is = ClassLoaderUtil.class.getClassLoader().getResourceAsStream(fileName);
    	Properties props = new Properties();
    	try {
    		if(is != null)
    			props.load(is);
    	} catch(Exception e) {
    	}
    	return props;

    }
}
